/* 
 * File:   TimeUtil.cpp
 * Author: batista
 * 
 * Created on 8 de Mar�o de 2013, 20:41
 */

#include "ShowMsg.h"
#include "TimeUtil.h"

TimeUtil::TimeUtil() {
}

TimeUtil::~TimeUtil() {
}

const char *word_c = "c7";
const char *word_a = "c3";

/**
 * Metodo responsavel por pegar a data e hora
 * e retornar ela no formato string
 * @return "Exemplo: 2010-10-25 10:00:00"
 */
string TimeUtil::getTime() {
    time_t now;
    struct tm *ts;
    char buf[80];
    char hora[80];
    int number;
    srand(time(NULL));

    /* generate secret number: */
    number = rand() % 1000 + 1;

    string str_number = ConvIntToString(number);

    if (number > 999) {
        str_number = "999";
    }

    if (number >= 10 && number < 100) {
        str_number = "0" + str_number;
    }

    if (number >= 0 && number < 10) {
        //so coloca um zero, pois str_number já vem com zero
        str_number = "0" + str_number;
    }


    // Get the current time
    time(&now);

    //Format and print the time, "ddd yyyy-mm-dd hh:mm:ss zzz"
    string str_format = "%Y-%m-%d %H:%M:%S." + str_number;
    ts = localtime(&now);
    strftime(buf, sizeof (buf), str_format.c_str(), ts);

    sprintf(hora, "%s", buf); //fu??o getTime usada para pegar a hora
    string newhora(hora);

    return newhora;
}
//Mon, 31 Dec 2007 23:59:59.000 GMT

string TimeUtil::getTimeRfc2822() {
    time_t now;
    struct tm ts;
    char buf[80];
    int number;
    srand(time(NULL));

    /* generate secret number: */
    number = rand() % 1000 + 1;

    string str_number = ConvIntToString(number);

    if (number > 999) {
        str_number = "999";
    }

    if (number >= 10 && number < 100) {
        str_number = "0" + str_number;
    }

    if (number >= 0 && number < 10) {
        //so coloca um zero, pois str_number já vem com zero
        str_number = "0" + str_number;
    }


    string str_format = "%a, %d %b %Y %H:%M:%S." + str_number + " GMT";
    // string str_format = "%a, %d %b %Y %H:%M:%S GMT";

    // Get current time
    time(&now);

    // Format time, "ddd yyyy-mm-dd hh:mm:ss zzz"
    ts = *localtime(&now);
    strftime(buf, sizeof (buf), str_format.c_str(), &ts);
    //printf("%s\n", buf);

    string newhora(buf);

    return newhora;
}

/**
 * Metodo resposavel por retornar uma data
 * para um formato informado.
 * @param format "%Y-%m-%d %H:%M:%S"
 * @return
 */
string TimeUtil::getTimeFormat(string format) {

    time_t now;
    struct tm *ts;
    char buf[80];
    char hora[80];

    // Get the current time
    time(&now);

    //Format and print the time, "ddd yyyy-mm-dd hh:mm:ss zzz"
    ts = localtime(&now); //"%Y-%m-%d %H:%M:%S"
    strftime(buf, sizeof (buf), format.c_str(), ts);

    sprintf(hora, "%s", buf); //fu��o getTime usada para pegar a hora
    string newhora(hora);

    return newhora;
}

void TimeUtil::SetDateStr(string str_date) {
    this->year = str_date.substr(0, 4);
    this->mth = str_date.substr(5, 2);
    this->day = str_date.substr(8, 2);
    this->mytime = str_date.substr(11, 2);
    this->min = str_date.substr(14, 2);
    this->seg = str_date.substr(17, 2);
}

/**
 * Metodo:getTimeNowInSeg(), retorno a hora atual
 * em segundo, em um long
 */
long TimeUtil::getTimeInSeg() {
    //  PrintMessage("HORA: "+mytime+"-"+min+"-"+seg, COLOR_BLUE, COLOR_GREEN);
    return (atoi(mytime.c_str()) * 3600)+(atoi(min.c_str()) * 60) + atoi(seg.c_str());
}

/**
 * Metodo: getDifBetweenTwoTime(string time1, string time2),
 * Responsavel por pegar a diferenca entre dois tempos em
 * segundos, e retornar
 * Exemplo: getDifBetweenTwoTime("08:00:00", "23:59:00")
 */
long TimeUtil::getDifBetweenTwoTime(string time1, string time2) {

    long time_long1 = (atoi(time1.substr(0, 2).c_str()) * 3600)+
            (atoi(time1.substr(3, 2).c_str()) * 60) +
            atoi(time1.substr(6, 2).c_str());

    long time_long2 = (atoi(time2.substr(0, 2).c_str()) * 3600)+
            (atoi(time2.substr(3, 2).c_str()) * 60) +
            atoi(time2.substr(6, 2).c_str());


    return (time_long2 - time_long1);
}

/**
 * Metodo: ValidAttendTime(string date_event, int time_out), Usado
 * para validar se o evento precisa ou n�o ser atualizado com ou sem
 * time-out. Verifica se o evento � do mesmo dia ou do dia anterior,
 * se o evento ultrapassou o tempo para ser atendido.
 * return true (para evento do dia anterior e para evento que ultra-
 * passou o tempo para ser atendido), false (para evento do mesmo dia
 * que esteja dentro do hor�rio)
 */
bool TimeUtil::ValidAttendTime(string date_info, int time_out) {
    //    Printmessage pmsg;
    TimeUtil mt2, mt1;
    long time1, time2, tot_time;

    //  string date_str = "2010-03-13 11:36:00";

    mt1.SetDateStr(date_info); //passo a data para calculo do timeout
    mt2.SetDateStr(mt2.getTime()); //pego hora atual do sistema

    /*    cout << "DATA DO SISTEMA:  " << mt2.getTime() + '\n'
                << "DATA DO EVENTO :  " << date_info + '\n'
                << "\nDATA DO SISTEMA EM SEGUNDOS:  " << mt2.getTimeInSeg() + '\n'
                << "\nDATA DO EVENTO EM SEGUNDOS :  " << mt1.getTimeInSeg() + '\n' << endl;
     */
    /**
     * Aqui, se o dia do evento for menor que o dia
     * atual, ent�o � verdadeiro, e vai atualizar
     * com time-out, s� ser� usado esse recuso no
     * caso da aplica��o cppappcall, que s? verifica
     * essa situa��o quando chega um novo evento que
     * pode ser que chegue s� no dia seguinte, ai ele
     * entra no if e retorna true
     */
    if (atoi(mt1.getDay().c_str()) < atoi(mt2.getDay().c_str()))
        return true;

    /**
     * Aqui, se o tempo atual menos o tempo do evento
     * informado for maior que o time-out, ent�o �
     * verdadeiro, e vai atualizar
     */
    time1 = mt1.getTimeInSeg(); //HORA INFORMA
    time2 = mt2.getTimeInSeg(); //HORA SYS
    //   pmsg.PrintMessage("HORA SYS: " + ConvIntToString(time2) + " - HORA INFORMA: " + ConvIntToString(time1), COLOR_BLUE, COLOR_CIANO);
    tot_time = (time2 - time1);
    //   pmsg.PrintMessage("HORA SYS EM SEGUNDOS: " + ConvIntToString(tot_time) + " E MAIOR QUE: " + ConvIntToString(time_out), COLOR_BLUE, COLOR_CIANO);

    if (tot_time > time_out)
        return true;

    return false;
}//fim do metodo que valida time-out

/**
 * funcao usada para somar minutos em uma hora, retornando
 * uma data com timeout do sistema
 */
string TimeUtil::SumTimeOut(string data_hora, long timeout) {

    /*      cout << "\nDentro de SumTimeOut\n"
                  << "\nData Hora: "<< data_hora
                  <<" Time Out " << timeout
                  << endl;
     */

    int ano = atoi(data_hora.substr(0, 4).c_str()); //pego o ano
    int mes = atoi(data_hora.substr(5, 2).c_str()); //pego o mes
    int dia = atoi(data_hora.substr(8, 2).c_str()); //pego o dia

    int hora = atoi(data_hora.substr(11, 2).c_str()); //pego a hora
    int min = atoi(data_hora.substr(14, 2).c_str()); //pego minutos
    int seg = atoi(data_hora.substr(17, 2).c_str()); //pego segundos

    int difminutos = 0;

    int min_seg = (min * 60);
    int total_segundos = min_seg + timeout + seg;


    /**
     * se a quantidade total de segundos for maio 3600, adiciono uma hora
     * para variavel hora, e subtraio a diferenca armazenando em difminutos.
     * depois, passo difminutos para minutos e armazeno na variavel (min).
     * caso a quantidade n?o seja superior a 3600, vou para o else, e passo
     * difminutos para minutos e armazeno na variavel (min) de minutos
     */
    if (total_segundos > 3600) {//3600 s?o 3600 segundos, que s?o 60 minutos
        hora++;
        difminutos = total_segundos - 3600;
        min = difminutos / 60;
    } else {
        min = total_segundos / 60;
    }

    //se minha hora for igual a 24 horas, mudo para 00
    if (hora == 24)
        hora = 00;

    string str_ano = ConvIntToString(ano);
    string str_mes = ConvIntToString(mes);
    string str_dia = ConvIntToString(dia);
    string str_time = ConvIntToString(hora);
    string str_min = ConvIntToString(min);
    string str_seg = ConvIntToString(seg);

    string date_time = str_ano + "-" + AddZeroLeft(str_mes) + "-" + AddZeroLeft(str_dia) + " " + AddZeroLeft(str_time) + ":" + AddZeroLeft(str_min) + ":" + AddZeroLeft(str_seg);
    //    cout << "retornando nova data: " << "\n" << date_time << endl;

    return date_time;
}//Fim SumTimeout

/**
 *  Fun??o usada para adicionar zero a esquerda
 *  de hora, minutos ou segundos
 */
string TimeUtil::AddZeroLeft(string str) {
    //
    string varstr;
    //
    if (str.length() < 2) {
        varstr += '0';
        varstr += str;
    } else {
        varstr = str;
    }

    return varstr;
}//adddir

/**
 * Metodo responsavel por converter um
 * long em uma string
 * @param number
 * @return string
 */
string TimeUtil::ConvLongToString(long number) {
    stringstream ss; //create a stringstream
    ss << number; //add number to the stream
    return ss.str(); //return a string with the contents of the stream
}

/**
 * Metodo responsavel por converter uma 
 * char para um long em string
 * @param c
 * @return 
 */
string TimeUtil::convCharToLong(char c) {
    long code = (int) c;
    stringstream str; //create a stringstream
    str << code; //add number to the stream
   // cout << str.str() << endl;
    //
    return str.str();
}

/**
 * funcao que converte de numerico
 * para string, e coloca zero a esquerda
 * de numero menor que 10
 */
string TimeUtil::ConvIntToString(int num) {
    char str[100];
    if (num < 10)
        sprintf(str, "0%d", num);
    else
        sprintf(str, "%d", num);
    return str;
}

/***
 * Dar uma pausa em milessimo de segundos\n
 * de (1 milessimo a 999.999 milessimo = a 1 segundo),
 * acima de 1000.000 = microsegundos\n
 * 1000 - milessimo de segundos = 1 segundos\n
 * 500  - milessimo de segundos = meio segundos\n
 * 100  - milessimo de segundos = 1 decimo de segundos\n 
 * 50   - milessimo de segundos = meio decimo de segundos\n
 * 10   - milessimo de segundos\n 
 * 1    - milessimo de segundos\n
 */
void TimeUtil::SleepSeg(long time_milissec) {
    int sec_in_milissec = (1000000 / 1000);
    usleep(time_milissec * sec_in_milissec); //valor em micro segundos
}

/**
 * Metodo responsavel por converter uma string char
 * para string numerica
 * @param strchar
 * @return  string
 */
string TimeUtil::ConvCharHexToString(char* strchar) {
    int numstr = strlen(strchar);
    char strcodetemp[3];

    char strcode[3];
    int i, j = 0;

    for (i = 0; i < numstr; i++) {
        if (i >= numstr - 2) {
            strcodetemp[j++] = strchar[i];
        }
    }
    strcodetemp[j++] = '\0';

    //Converte de charhex para inteiro
    int event_room_code = static_cast<int> (strtol(strcodetemp, NULL, 16));

    //Converte de inteiro para string
    sprintf(strcode, "%d", event_room_code);

    return strcode;
}

/**
 * Metodo responsavel por remover spacos
 * a direita de numero.
 * @param str
 * @return string
 */
string TimeUtil::CleanRightSpace(string str) {
    string strtemp;
    for (int i = 0; i < str.length(); i++) {
        if (str[i] != ' ') {
            strtemp += str[i];
        }
    }
    return strtemp;
}

/**
 * Metodo responsavel por fazer a trocar dos caracteres
 * (A e C) sem acentua��o, para caracteres com acentua��o.
 * @param oldstr
 * @return
 */
string TimeUtil::ChangeStrHexString(string oldstr) {
    string newstr;
    //FIM HIGIENIZA��O//POSICAO 14=A, 13=C
    //INICIO HIGIENIZA��O       16=C, 17=A

    char strcode;

    for (int i = 0; i < oldstr.length(); i++) {
        //        cout << oldstr[i] << i << endl;

        if (oldstr[i] == 'C' && i == 13 ||
                oldstr[i] == 'C' && i == 16 ||
                oldstr[i] == 'A' && i == 14 ||
                oldstr[i] == 'A' && i == 17) {

            if (i == 14 && oldstr[i] == 'A' || i == 17 && oldstr[i] == 'A') {
                //Converte de inteiro para string
                //               cout << "Trocando letra A" << endl;
                strcode = static_cast<char> (strtol(word_a, NULL, 16));
                newstr += strcode;
            } else {
                //               cout << "Trocando letra C" << endl;
                //Converte de inteiro para string
                strcode = static_cast<char> (strtol(word_c, NULL, 16));
                newstr += strcode;
            }
        } else {
            newstr += oldstr[i];
        }
    }

    return newstr;
}

string TimeUtil::StringHexToStringInteger(string str_code_hexa) {
    //
    unsigned long hexa_code;

    std::stringstream stream_hexa;
    stream_hexa << std::hex << str_code_hexa;
    stream_hexa >> hexa_code;

    cout << hexa_code << endl;

    stringstream stream_code; //create a stringstream
    stream_code << hexa_code; //add number to the stream
    //
    string str_hexa_code(stream_code.str());
    //
    return str_hexa_code;
}

/**
 * Metodo responsavel por converter 
 * uma string para ulong hexa
 * @param str_hex
 * @return 
 */
ulong TimeUtil::StrToUlong(string str_hex) {
    char *p;
    //
    ulong reshex = strtol(str_hex.c_str(), &p, 16);
    //
    if (*p != 0) {
        cout << "fail" << endl;
    }
    //
    return reshex;
}

/**
 * Metodo responsavel por retorna verdadeiro 
 * quando encontrar a primeira ocorrencia
 * para o (char) informado.
 * @param array
 * @param c
 * @return true ou false
 */
bool TimeUtil::containsChar(const char* array, char c) {
    char f;
    //
    for (int i = 0; i < strlen(array); i++) {
        f = array[i];
        //se encontrar retorna true         
        if (toupper(f) == toupper(c)) {
            cout << FG_BLUE << "TRUE --> " << FG_MAGENTA << hex << (int) toupper(c) << endl;
            return true;
        }
    }
    cout << FG_BLUE << "FALSE --> " << FG_MAGENTA << hex << (int) toupper(f) << endl;
    //
    return false;
}

/**
 * Metodo responsavel por adicionar um char de controle
 * para mensagem de pager.
 * @param array
 * @param c
 * @return 
 */
char * TimeUtil::addStrCharToMessage(char c) {
    int i = 0;
    static char buffer[255];
    //
    buffer[i++] = c;
    for (i; i < 255; i++) buffer[i] = '\0';
    //cout << FG_BLUE << "Buffer --> " << FG_CIANO << buffer << endl;
    //
    return buffer;
}

/**
 * Metodo responsavel por adicionar os chas de control
 * para mensagem de pager.
 * @param array
 * @param c
 * @return 
 */
char * TimeUtil::addStrCharToMessage(const char* array, char c) {
    int i;
    static char buffer[255];
    //
    for (i = 0; i < strlen(array); i++) {
        buffer[i] = array[i];
    }
    //
    buffer[i++] = c;
    for (i; i < 255; i++) buffer[i] = '\0';
    //cout << FG_BLUE << "Buffer --> " << FG_CIANO << buffer << endl;
    //
    return buffer;
}

/**
 * Metodo responsavel por adicionar os chas de control
 * para mensagem de pager.
 * @param array
 * @param c
 * @return 
 */
char * TimeUtil::addStrCharToMessage(const char* array) {
    int i;
    static char buffer[255];
    //
    for (i = 0; i < strlen(array); i++) {
        buffer[i] = array[i];
    }
    for (i; i < 255; i++) buffer[i] = '\0';
    //cout << FG_BLUE << "Buffer --> " << FG_CIANO << buffer << endl;
    //
    return buffer;
}


/**
 * Metodo responsavel por somar um
 * array no final do outro
 * @param array
 * @param c
 * @return 
 */
char * TimeUtil::addStrCharToMessage(const char* array, const char* c) {
    int i;
    static char buffer[255];
    //
    for (i = 0; i < strlen(array); i++) {
        buffer[i] = array[i];
    }

    for (int j = 0; j < strlen(c); j++) {
        buffer[i++] = c[j];
    }
    //
    for (i; i < 255; i++) buffer[i] = '\0';
    //
    //cout << FG_BLUE << "Buffer --> " << FG_MAGENTA << buffer << endl;
    //
    return buffer;
}

